package com.central.apps.handler.project;

import com.central.app.common.base.BaseHandler;
import com.central.app.service.FlowCommonService;
import com.central.app.service.HandlerService;
import com.central.apps.common.util.MapCustomUtils;
import com.central.apps.service.TableService;
import com.central.apps.service.TaskService;
import com.central.app.service.VersionService;
import com.central.bizcommon.model.flow.FlowNode;
import com.central.bizcommon.model.flow.FlowOpinion;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.*;

/**
 * 处理变更管理业务逻辑
 *
 * @author lidachao
 * @date 2022/9/16
 */
@Component
@Slf4j
public class ProjectChangeHandler extends BaseHandler {

    @Autowired
    private HandlerService handlerService;
    @Autowired
    private TableService tableService;
    @Autowired
    private VersionService versionService;
    @Autowired
    private FlowCommonService flowCommonService;
    @Autowired
    private TaskService taskService;

    @Override
    public String validateSave(String app, String objName, Map<String, Object> data) throws Exception {
        if ("gq_prochange".equals(objName)) {
            // 判断是否存在多份项目变更
            Integer id = MapUtils.getInteger(data, "id");
            Integer proId = MapUtils.getInteger(data, "proid");
            String chgBudget = MapUtils.getString(data, "chgbudget");
            String chgPlan = MapUtils.getString(data, "chgplan");
            String chgResource = MapUtils.getString(data, "chgresource");
            String chgDeliverables = MapUtils.getString(data, "chgdeliverables");

            StringBuilder sql = new StringBuilder();
            sql.append("select id from gq_prochange where proid = ").append(proId).append(" and status not in ('已批准', '已作废') ");

            if (id != null) {
                sql.append(" and id != ").append(id);
            }

            StringBuilder sqlChild = new StringBuilder();
            if ("1".equals(chgBudget)) {
                String year = MapUtils.getString(data, "year");
                sqlChild.append(" (chgbudget = '1' and year = '").append(year).append("') ");
            }
            if ("1".equals(chgPlan)) {
                if (StringUtils.isNotEmpty(sqlChild.toString())) {
                    sqlChild.append(" or ");
                }
                sqlChild.append(" (chgplan = '1') ");
            }
            if ("1".equals(chgResource)) {
                if (StringUtils.isNotEmpty(sqlChild.toString())) {
                    sqlChild.append(" or ");
                }
                sqlChild.append(" (chgresource = '1') ");
            }
            if ("1".equals(chgDeliverables)) {
                if (StringUtils.isNotEmpty(sqlChild.toString())) {
                    sqlChild.append(" or ");
                }
                sqlChild.append(" (chgdeliverables = '1') ");
            }

            if (StringUtils.isNotEmpty(sqlChild.toString())) {
                sql.append(" and (").append(sqlChild).append(")");
            }

            List<Map<String, Object>> list = handlerService.findBySql(sql.toString());

            if (CollectionUtils.isNotEmpty(list)) {
                return "课题号存在未完成的变更申请, 请先完成之前的变更申请流程!";
            }

            // 校验预算不能小于占用+实际发生金额
            if (id != null && "1".equals(chgBudget)) {
                // 查询项目变更年度预算变更
                list = handlerService.findBySql("select pbidid, pbiid, budgetitem, budgetamt, newbudgetamt from gq_pcbudget where pbiid > 0 and budgetamt != newbudgetamt and delflag = '0' and pcid = " + id);

                if (CollectionUtils.isNotEmpty(list)) {
                    StringBuilder promptStr = new StringBuilder();
                    String year = MapUtils.getString(data, "year");

                    for (Map<String, Object> map : list) {
                        Integer pbiid = MapUtils.getInteger(map, "pbiid");
                        String budgetAmt = MapUtils.getString(map, "budgetamt");
                        String newBudgetAmt = MapUtils.getString(map, "newbudgetamt");

                        BigDecimal budgetAmtDec = new BigDecimal(budgetAmt);
                        BigDecimal newBudgetAmtDec = new BigDecimal(newBudgetAmt);

                        if (newBudgetAmtDec.compareTo(budgetAmtDec) < 0) {
                            Map<String, Object> pbMap = handlerService.findOneBySql("select id from gq_probudget where pbiid = " + pbiid
                                    + " and proid = " + proId + " and year = '" + year + "' and occupyamt + actualamt > " + newBudgetAmtDec);

                            if (pbMap != null && !pbMap.isEmpty()) {
                                String budgetItem = MapUtils.getString(map, "budgetitem");
                                promptStr.append(budgetItem).append(",");
                            }
                        }
                    }

                    if (StringUtils.isNotEmpty(promptStr.toString())) {
                        promptStr.deleteCharAt(promptStr.length() - 1);
                        promptStr.append("等预算项变更的预算金额小于年度预算占用和实际发生金额的总和, 请重新进行编制!");
                    }
                }
            }

            // 校验项目资源禁用逻辑
            if ("1".equals(chgResource)) {
                return judgeResource(data, chgResource);
            }
        }

        return null;
    }

    @Override
    public void beforSave(String app, String objName, Map<String, Object> data, boolean isUpdate) throws Exception {
        if (isUpdate && "gq_prochange".equals(objName)) {
            Integer id = MapUtils.getInteger(data, "id");
            // 查询变更信息
            List<Map<String, Object>> list = handlerService.findBySql("select proid from gq_prochange where id = " + id);
            Map<String, Object> map = list.get(0);
            Integer newProId = MapUtils.getInteger(data, "proid");
            Integer proId = MapUtils.getInteger(map, "proid");

            if (!newProId.equals(proId)) {
                // 删除项目年度预算变更信息
                handlerService.updateBySql("delete from gq_pcbudget where pcid = " + id);
                // 删除项目资源变更信息
                handlerService.updateBySql("delete from gq_prdetailchg where pcid = " + id);
                handlerService.updateBySql("delete from gq_prdetailchgnew where pcid = " + id);
                // 删除项目产出计划变更信息
                handlerService.updateBySql("delete from gq_popdtlchg where pcid = " + id);
                handlerService.updateBySql("delete from gq_popdtlchgnew where pcid = " + id);
                // 删除项目年度计划变更信息
                handlerService.updateBySql("delete from gq_pctaskchg where pcid = " + id);
                handlerService.updateBySql("delete from gq_taskdelichg where pcid = " + id);

                // 删除项目计划变更详细信息
                handlerService.updateBySql("delete from gq_pctaskchgdtl where pcid = " + id);
                handlerService.updateBySql("delete from gq_pctaskchgdel where pcid = " + id);
                handlerService.updateBySql("delete from gq_pctaskchgnew where pcid = " + id);
            }
        }
    }

    @Override
    public void afterSave(String app, String objName, Map<String, Object> data, boolean isUpdate) throws Exception {
        // 保存主表信息后
        if ("gq_prochange".equals(objName)) {
            Integer pcId = MapUtils.getInteger(data, "id");
            Integer proId = MapUtils.getInteger(data, "proid");
            String chgResource = MapUtils.getString(data, "chgresource");
            String chgDeliverables = MapUtils.getString(data, "chgdeliverables");
            String chgBudget = MapUtils.getString(data, "chgbudget");
            String chgPlan = MapUtils.getString(data, "chgplan");

            if ("1".equals(chgBudget)) {
                List<Map<String, Object>> judgeList = handlerService.findBySql("select id from gq_pcbudget where pcid = " + pcId);

                if (CollectionUtils.isEmpty(judgeList)) {
                    String year = MapUtils.getString(data, "year");
                    // 批量插入年度预算到预算变更表
                    insertBudget(proId, year, pcId);
                }
            } else {
                // 删除预算历史信息
                handlerService.updateBySql("delete from gq_pcbudget where pcid = " + pcId);
            }

            if ("1".equals(chgPlan)) {
                List<Map<String, Object>> judgeList = handlerService.findBySql("select id from gq_pctaskchg where pcid = " + pcId);

                if (CollectionUtils.isEmpty(judgeList)) {
                    // 批量插入项目年度计划到变更表
                    insertTaskPlan(proId, pcId);
                }
            } else {
                // 删除项目年度计划信息
                handlerService.updateBySql("delete from gq_pctaskchg where pcid = " + pcId);
            }

            if ("1".equals(chgResource)) {
                List<Map<String, Object>> judgeList = handlerService.findBySql("select id from gq_prdetailchg where pcid = " + pcId);

                if (CollectionUtils.isEmpty(judgeList)) {
                    // 批量插入项目资源到变更表
                    insertResources(proId, pcId);
                }
            } else {
                // 删除项目资源历史信息
                handlerService.updateBySql("delete from gq_prdetailchg where pcid = " + pcId);
                handlerService.updateBySql("delete from gq_prdetailchgnew where pcid = " + pcId);
            }

            if ("1".equals(chgDeliverables)) {
                List<Map<String, Object>> judgeList = handlerService.findBySql("select id from gq_popdtlchg where pcid = " + pcId);

                if (CollectionUtils.isEmpty(judgeList)) {
                    // 批量插入项目产出计划到变更表
                    insertOutputPlan(proId, pcId);
                }
            } else {
                // 删除项目产出计划变更信息
                handlerService.updateBySql("delete from gq_popdtlchg where pcid = " + pcId);
                handlerService.updateBySql("delete from gq_popdtlchgnew where pcid = " + pcId);
            }
        }
    }

    @Override
    public String beforeExcuteFlow(String app, Long id, FlowNode flowNode, FlowOpinion op) throws Exception {
        Map<String, Object> map = op.getVariables();
        // 校验项目变更信息，至少选择一项进行变更
        String chgBaseInfo = MapUtils.getString(map, "chgbaseinfo");
        String chgResource = MapUtils.getString(map, "chgresource");
        String chgDeliverables = MapUtils.getString(map, "chgdeliverables");
        String chgBudget = MapUtils.getString(map, "chgbudget");
        String chgPlan = MapUtils.getString(map, "chgplan");
        String year = MapUtils.getString(map, "year");
        Integer proId = MapUtils.getInteger(map, "proid");

        if ("capture".equals(flowNode.getId())) {
            if ("0".equals(chgBaseInfo) && "0".equals(chgResource) && "0".equals(chgDeliverables) && "0".equals(chgBudget) && "0".equals(chgPlan)) {
                return "至少选择一项信息进行变更!";
            }

            boolean existBudget = true;
            boolean existPlan = true;
            boolean existResource = true;
            boolean existDeliverables = true;
            // 判断是否存在预算变更信息
            if ("1".equals(chgBudget)) {
                List<Map<String, Object>> list = handlerService.findBySql("select id from gq_pcbudget where pcid = " + id);

                if (CollectionUtils.isEmpty(list)) {
                    existBudget = false;
                }
            }
            // 判断是否存在计划变更信息
            if ("1".equals(chgPlan)) {
                List<Map<String, Object>> list = handlerService.findBySql("select id from gq_pctaskchg where pcid = " + id);

                if (CollectionUtils.isEmpty(list)) {
                    existPlan = false;
                }
            }
            // 判断是否存在资源变更信息
            if ("1".equals(chgResource)) {
                List<Map<String, Object>> list = handlerService.findBySql("select id from gq_prdetailchg where pcid = " + id);

                if (CollectionUtils.isEmpty(list)) {
                    list = handlerService.findBySql("select id from gq_prdetailchgnew where pcid = " + id);

                    if (CollectionUtils.isEmpty(list)) {
                        existResource = false;
                    }
                }
            }
            // 判断是否存在产出计划变更信息
            if ("1".equals(chgDeliverables)) {
                List<Map<String, Object>> list = handlerService.findBySql("select id from gq_popdtlchg where pcid = " + id);

                if (CollectionUtils.isEmpty(list)) {
                    list = handlerService.findBySql("select id from gq_popdtlchgnew where pcid = " + id);

                    if (CollectionUtils.isEmpty(list)) {
                        existDeliverables = false;
                    }
                }
            }

            StringBuilder promptStr = new StringBuilder();
            if (!existBudget) {
                promptStr.append("年度预算变更").append(",");
            }
            if (!existPlan) {
                promptStr.append("年度计划变更").append(",");
            }
            if (!existResource) {
                promptStr.append("项目资源变更").append(",");
            }
            if (!existDeliverables) {
                promptStr.append("产出计划变更").append(",");
            }

            if (StringUtils.isNotEmpty(promptStr.toString())) {
                promptStr.deleteCharAt(promptStr.length() - 1);
                promptStr.append("等信息未编辑不能进行提交!");
            }

            // WBS任务是否存在负责人为空数据
            List<Map<String, Object>> list = handlerService.findBySql("select * from gq_pctaskchg where parentId != 0 and (manager = 0 or manager is null) and pcid = " + id);

            if (CollectionUtils.isNotEmpty(list)) {
                return "存在任务未分配负责人!";
            }

            // 更新任务数据是否只读状态
            if ("1".equals(chgPlan)) {
                handlerService.updateBySql("update gq_pctaskchg set isreadonly = 1 where pcid = " + id);

                // 删除任务相关变更信息
                handlerService.updateBySql("delete from gq_pctaskchgdtl where pcid = " + id);
                handlerService.updateBySql("delete from gq_pctaskchgnew where pcid = " + id);
                handlerService.updateBySql("delete from gq_pctaskchgdel where pcid = " + id);
                handlerService.updateBySql("delete from gq_taskdelichgnew where pcid = " + id);
                handlerService.updateBySql("delete from gq_taskdelichgdtl where pcid = " + id);
                handlerService.updateBySql("delete from gq_taskdelichgdel where pcid = " + id);

                // 存储任务的变更和新增信息
                combineTaskInfo(proId, id.intValue());
            }
        }

        if("complete".equals(flowNode.getId()) && op.isFlag()) {
            // 处理项目基础信息变更信息
            if ("1".equals(chgBaseInfo)) {
                // 处理项目基础信息变更信息
                dealBaseInfo(map, proId);
            }

            // 处理项目预算变更信息
            if ("1".equals(chgBudget)) {
                dealBudget(proId, year, id.intValue());
            }

            // 处理项目计划变更信息
            if ("1".equals(chgPlan)) {
                dealTask(proId, id.intValue());
            }

            // 处理项目资源变更信息
            if ("1".equals(chgResource)) {
                // 存储项目资源新版本
                List<Map<String, Object>> proResourceList = handlerService.findBySql("select * from gq_proresource where proid = " + proId);
                if (CollectionUtils.isNotEmpty(proResourceList)) {
                    String conditionStr = " proid = " + proId;
                    versionService.saveData("gq_proresource", conditionStr, proResourceList);
                }

                // 查询项目资源变更信息
                List<Map<String, Object>> list = handlerService.findBySql("select * from gq_prdetailchg where pcid = " + id + " and proid = " + proId);

                if (CollectionUtils.isNotEmpty(list)) {
                    // 处理项目资源变更信息
                    dealResource(proId, list);
                }

                list = handlerService.findBySql("select * from gq_prdetailchgnew where pcid = " + id + " and proid = " + proId);

                if (CollectionUtils.isNotEmpty(list)) {
                    // 处理项目资源变更信息
                    dealNewResource(list);
                }
            }

            // 处理项目产出计划变更信息
            if ("1".equals(chgDeliverables)) {
                // 存储项目资源新版本
                List<Map<String, Object>> proOutputList = handlerService.findBySql("select * from gq_pbloutputplan where proid = " + proId);
                if (CollectionUtils.isNotEmpty(proOutputList)) {
                    String conditionStr = " proid = " + proId;
                    versionService.saveData("gq_pbloutputplan", conditionStr, proOutputList);
                }

                // 查询项目产出计划变更信息
                List<Map<String, Object>> list = handlerService.findBySql("select * from gq_popdtlchg where pcid = " + id + " and proid = " + proId);

                if (CollectionUtils.isNotEmpty(list)) {
                    // 处理项目产出计划变更信息
                    dealOutputPlan(proId, list);
                }

                // 查询项目产出计划新增信息
                list = handlerService.findBySql("select * from gq_popdtlchgnew where pcid = " + id + " and proid = " + proId);

                if (CollectionUtils.isNotEmpty(list)) {
                    // 处理项目产出计划变更信息
                    dealNewOutputPlan(list);
                }
            }
        }
        return null;
    }

    @Override
    public void addFlowVar(String app, Long id, FlowNode flowNode, FlowOpinion op, Map<String, Object> variables) throws Exception {
        Integer proId = MapUtils.getInteger(variables, "proid");
        String chgBudget = MapUtils.getString(variables, "chgbudget");
        String chgPlan = MapUtils.getString(variables, "chgplan");
        variables.put("overMilestone", 0);
        variables.put("overBudget", 0);

        // 1.处理项目概算判断
        // 校验预算变更是否影响到项目概算
        if ("1".equals(chgBudget)) {
            // 查询项目变更年度预算变更
            List<Map<String, Object>> list = handlerService.findBySql("select pbidid, pbiid, budgetamt, newbudgetamt from gq_pcbudget where pbiid > 0 and budgetamt != newbudgetamt and delflag = '0' and pcid = " + id);

            if (CollectionUtils.isNotEmpty(list)) {
                for (Map<String, Object> map : list) {
                    Integer pbiid = MapUtils.getInteger(map, "pbiid");
                    BigDecimal budgetAmt = new BigDecimal(MapUtils.getString(map, "budgetamt"));
                    BigDecimal newBudgetAmt = new BigDecimal(MapUtils.getString(map, "newbudgetamt"));

                    if (newBudgetAmt.compareTo(budgetAmt) > 0) {
                        // 查询项目概算
                        Map<String, Object> pbMap = handlerService.findOneBySql("select id, applyamt, budgetamt from gq_pblbestimate where proid = " + proId + " and pbiid = " + pbiid);
                        BigDecimal applyAmt = new BigDecimal(MapUtils.getString(pbMap, "applyamt"));
                        BigDecimal pBudgetAmt = new BigDecimal(MapUtils.getString(pbMap, "budgetamt"));

                        applyAmt = applyAmt.add(newBudgetAmt.subtract(budgetAmt));

                        if (applyAmt.compareTo(pBudgetAmt) > 0) {
                            variables.put("overBudget", 1);
                            break;
                        }
                    }
                }
            }
        }

        // 2.处理里程碑判断
        if ("1".equals(chgPlan)) {
            // 查询项目变更年度预算变更
            List<Map<String, Object>> list = handlerService.findBySql("select mlid, startTime, endTime from gq_pctaskchg where mlid > 0 and delflag = '0' and pcid = " + id);

            if (CollectionUtils.isNotEmpty(list)) {
                for (Map<String, Object> map : list) {
                    Integer mlid = MapUtils.getInteger(map, "mlid");
                    // 查询项目概算
                    Map<String, Object> mlMap = handlerService.findOneBySql("select startTime, endTime from gq_pblmilestone where proid = " + proId + " and id = " + mlid);
                    Date endTime = (Date) MapUtils.getObject(map, "endTime");
                    Date mlEndTime = (Date) MapUtils.getObject(mlMap, "endTime");

                    if (endTime.after(mlEndTime)) {
                        variables.put("overMilestone", 1);
                        break;
                    }
                }
            }
        }
    }

    @Override
    public void afterMoveNode(String app, Long id) throws Exception {
        List<Map<String, Object>> list = handlerService.findBySql("select chgplan, status from gq_prochange where id = " + id);
        Map<String, Object> map = list.get(0);
        String chgPlan = MapUtils.getString(map, "chgplan");
        boolean isReturnInitNode = flowCommonService.isSubmitNode(app, id);

        if (isReturnInitNode && "1".equals(chgPlan)) {
            handlerService.updateBySql("update gq_pctaskchg set isreadonly = 0 where pcid = " + id);
        }
    }

    /**
     * 存储任务的变更和新增信息
     *
     * @param proId
     * @param pcId
     */
    private void combineTaskInfo(Integer proId, Integer pcId) throws Exception {
        // 查询计划信息
        List<Map<String, Object>> proTaskList = handlerService.findBySql("select * from gq_scheduleplantask where proid = " + proId + " order by recordId");
        // 查询任务计划变更信息
        List<Map<String, Object>> taskChgList = handlerService.findBySql("select * from gq_pctaskchg where pcid = " + pcId);

        if (CollectionUtils.isNotEmpty(taskChgList)) {
            Map<String, List<String>> convertMap = new HashMap<>();
            convertMap.computeIfAbsent("description", key -> new ArrayList<>()).add("newdescription");
            convertMap.computeIfAbsent("startTime", key -> new ArrayList<>()).add("newstartTime");
            convertMap.computeIfAbsent("endTime", key -> new ArrayList<>()).add("newendTime");
            convertMap.computeIfAbsent("duration", key -> new ArrayList<>()).add("newduration");
            convertMap.computeIfAbsent("managername", key -> new ArrayList<>()).add("newmanagername");
            convertMap.computeIfAbsent("predecessorsdesc", key -> new ArrayList<>()).add("newpredecessorsdesc");
            convertMap.computeIfAbsent("assignsdesc", key -> new ArrayList<>()).add("newassignsdesc");
            convertMap.computeIfAbsent("parentname", key -> new ArrayList<>()).add("newparentname");
            convertMap.computeIfAbsent("iswarnflag", key -> new ArrayList<>()).add("newiswarnflag");
            convertMap.computeIfAbsent("taskrisk", key -> new ArrayList<>()).add("newtaskrisk");
            convertMap.computeIfAbsent("controlmeasures", key -> new ArrayList<>()).add("newcontrolmeasures");
            convertMap.computeIfAbsent("tasklevel", key -> new ArrayList<>()).add("newtasklevel");

            List<String> expFields = new ArrayList<>();
            expFields.add("id");
            expFields.add("createtime");
            expFields.add("createuser");
            expFields.add("createuserdesc");
            expFields.add("updatetime");
            expFields.add("updateuser");
            expFields.add("status");
            expFields.add("taskstatus");
            expFields.add("version");
            expFields.add("recordId");
            expFields.add("uniqueId");
            expFields.add("hasChild");

            // 处理变更信息->显示的展示WBS变化数据
            taskService.dealChgInfo("prochangeApp", "pcid", pcId, "gq_pctaskchg", "taskid", "gq_scheduleplantask", "gq_pctaskchgdtl",
                    "gq_pctaskchgnew", "gq_pctaskchgdel", taskChgList, proTaskList, convertMap, expFields);

            // 查询交付物变更信息
            List<Map<String, Object>> chgList = handlerService.findBySql("select * from gq_taskdelichg where pcid = " + pcId);
            // 查询交付物计划信息
            List<Map<String, Object>> deliList = handlerService.findBySql("select * from gq_taskdeliverables where proid = " + proId);

            convertMap = new HashMap<>();
            convertMap.computeIfAbsent("delname", key -> new ArrayList<>()).add("newdelname");
            convertMap.computeIfAbsent("deltype", key -> new ArrayList<>()).add("newdeltype");
            convertMap.computeIfAbsent("delcategory", key -> new ArrayList<>()).add("newdelcategory");
            convertMap.computeIfAbsent("remarks", key -> new ArrayList<>()).add("newremarks");
            convertMap.computeIfAbsent("isprodeli", key -> new ArrayList<>()).add("newisprodeli");
            convertMap.computeIfAbsent("deltypeid", key -> new ArrayList<>()).add("newdeltypeid");
            convertMap.computeIfAbsent("deltypenum", key -> new ArrayList<>()).add("newdeltypenum");
            convertMap.computeIfAbsent("delcategoryid", key -> new ArrayList<>()).add("newdelcategoryid");
            convertMap.computeIfAbsent("delcategorynum", key -> new ArrayList<>()).add("newdelcategorynum");

            expFields = new ArrayList<>();
            expFields.add("id");
            expFields.add("createtime");
            expFields.add("createuser");
            expFields.add("createuserdesc");
            expFields.add("updatetime");
            expFields.add("updateuser");
            expFields.add("status");
            expFields.add("version");
            expFields.add("olddeliid");
            expFields.add("pcid");
            expFields.add("pctaskid");

            // 处理交付物变更信息
            taskService.dealChgInfo("prochangeApp", "pcid", pcId, "gq_taskdelichg", "olddeliid", "gq_taskdeliverables", "gq_taskdelichgdtl",
                    "gq_taskdelichgnew", "gq_taskdelichgdel", chgList, deliList, convertMap, expFields);
        }
    }

    /**
     * 判断资源禁用逻辑
     *
     * @param data
     * @param chgResources
     * @return
     */
    private String judgeResource(Map<String, Object> data, String chgResources) {
        // 获取项目资源变更信息
        List<Map<String, Object>> list = MapCustomUtils.combineChildChgList(data, "TableUKey84640");

        if (CollectionUtils.isNotEmpty(list)) {
            StringBuilder sb = new StringBuilder();
            for (Map<String, Object> map : list) {
                Integer prId = MapUtils.getInteger(map, "prid");
                List<Map<String, Object>> planList = null;
                if ("1".equals(chgResources)) {
                    planList = handlerService.findBySql("select id from gq_pctaskchg where status != '已完成' and (manager= " + prId + " or find_in_set('" + prId + "', assigns))");
                } else {
                    planList = handlerService.findBySql("select id from gq_scheduleplantask where status != '已完成' and (manager= " + prId + " or find_in_set('" + prId + "', assigns))");
                }

                if (CollectionUtils.isNotEmpty(planList)) {
                    sb.append(MapUtils.getString(map, "prname")).append(",");
                }
            }

            if (StringUtils.isNotEmpty(sb.toString())) {
                sb.deleteCharAt(sb.length() - 1);
                sb.append("等禁用的资源存在于任务对应的负责人或分配资源, 请首先变更相关信息再禁用资源!");

                return sb.toString();
            }
        }

        return null;
    }

    /**
     * 批量插入预算信息到变更表
     *
     * @param proId
     * @param year
     * @param pcId
     */
    private void insertBudget(Integer proId, String year, Integer pcId) throws Exception {
        List<Map<String, Object>> list = handlerService.findBySql("select * from gq_probudget where proid = " + proId + " and year = '" + year + "'");

        if (CollectionUtils.isNotEmpty(list)) {
            Map<String, List<String>> convertMap = new HashMap<>();
            convertMap.computeIfAbsent("id", key -> new ArrayList<>()).add("pbidid");
            convertMap.computeIfAbsent("budgetamt", key -> new ArrayList<>()).add("newbudgetamt");
            convertMap.computeIfAbsent("subjectnum", key -> new ArrayList<>()).add("newsubjectnum");
            convertMap.computeIfAbsent("subjectdesc", key -> new ArrayList<>()).add("newsubjectdesc");
            convertMap.computeIfAbsent("crdr", key -> new ArrayList<>()).add("newcrdr");

            List<Map<String, Object>> insertList = new ArrayList<>();
            for (Map<String, Object> map : list) {
                Map<String, Object> addMap = tableService.convertMap("gq_probudget", "gq_pcbudget", map, convertMap, null);
                addMap.put("pcid", pcId);// 项目变更id
                insertList.add(addMap);
            }

            if (CollectionUtils.isNotEmpty(insertList)) {
                handlerService.batchInsert("prochangeApp", "gq_pcbudget", insertList);
            }
        }
    }

    /**
     * 批量插入项目资源到变更表
     *
     * @param proid
     * @param pcid
     */
    private void insertResources(Integer proid, Integer pcid) throws Exception {
        List<Map<String, Object>> list = handlerService.findBySql("select * from gq_proresource where delflag = '0' and proid = " + proid);

        if (CollectionUtils.isNotEmpty(list)) {
            Map<String, List<String>> convertMap = new HashMap<>();
            convertMap.computeIfAbsent("id", key -> new ArrayList<>()).add("prdid");
            convertMap.computeIfAbsent("prid", key -> new ArrayList<>()).add("newprid");
            convertMap.computeIfAbsent("prnum", key -> new ArrayList<>()).add("newprnum");
            convertMap.computeIfAbsent("prname", key -> new ArrayList<>()).add("newprname");
            convertMap.computeIfAbsent("deptid", key -> new ArrayList<>()).add("newdeptid");
            convertMap.computeIfAbsent("deptcode", key -> new ArrayList<>()).add("newdeptcode");
            convertMap.computeIfAbsent("deptname", key -> new ArrayList<>()).add("newdeptname");
            convertMap.computeIfAbsent("prcategoryid", key -> new ArrayList<>()).add("newprcategoryid");
            convertMap.computeIfAbsent("prcategorynum", key -> new ArrayList<>()).add("newprcategorynum");
            convertMap.computeIfAbsent("prcategoryname", key -> new ArrayList<>()).add("newprcategoryname");
            convertMap.computeIfAbsent("prtype", key -> new ArrayList<>()).add("newprtype");
            convertMap.computeIfAbsent("duty", key -> new ArrayList<>()).add("newduty");
            convertMap.computeIfAbsent("status", key -> new ArrayList<>()).add("newstatus");

            List<Map<String, Object>> insertList = new ArrayList<>();
            for (Map<String, Object> map : list) {
                Map<String, Object> addMap = tableService.convertMap("gq_proresource", "gq_prdetailchg", map, convertMap, null);
                addMap.put("pcid", pcid);// 项目变更id
                addMap.put("status", map.get("status"));
                insertList.add(addMap);
            }

            if (CollectionUtils.isNotEmpty(insertList)) {
                handlerService.batchInsert("prochangeApp", "gq_prdetailchg", insertList);
            }
        }
    }

    /**
     * 批量插入项目产出计划到变更表
     *
     * @param proid
     * @param pcid
     */
    private void insertOutputPlan(Integer proid, Integer pcid) throws Exception {
        List<Map<String, Object>> list = handlerService.findBySql("select * from gq_pbloutputplan where status = '未交付' and proid = " + proid);

        if (CollectionUtils.isNotEmpty(list)) {
            Map<String, List<String>> convertMap = new HashMap<>();
            convertMap.computeIfAbsent("id", key -> new ArrayList<>()).add("popdid");
            convertMap.computeIfAbsent("delcategoryid", key -> new ArrayList<>()).add("newdelcategoryid");
            convertMap.computeIfAbsent("delcategorynum", key -> new ArrayList<>()).add("newdelcategorynum");
            convertMap.computeIfAbsent("delcategory", key -> new ArrayList<>()).add("newdelcategory");
            convertMap.computeIfAbsent("deltypeid", key -> new ArrayList<>()).add("newdeltypeid");
            convertMap.computeIfAbsent("deltypenum", key -> new ArrayList<>()).add("newdeltypenum");
            convertMap.computeIfAbsent("deltype", key -> new ArrayList<>()).add("newdeltype");
            convertMap.computeIfAbsent("delname", key -> new ArrayList<>()).add("newdelname");
            convertMap.computeIfAbsent("starttime", key -> new ArrayList<>()).add("newstarttime");
            convertMap.computeIfAbsent("endtime", key -> new ArrayList<>()).add("newendtime");

            List<Map<String, Object>> insertList = new ArrayList<>();
            for (Map<String, Object> map : list) {
                Map<String, Object> addMap = tableService.convertMap("gq_pbloutputplan", "gq_popdtlchg", map, convertMap, null);
                addMap.put("pcid", pcid);// 项目变更id
                insertList.add(addMap);
            }

            if (CollectionUtils.isNotEmpty(insertList)) {
                handlerService.batchInsert("prochangeApp", "gq_popdtlchg", insertList);
            }
        }
    }

    /**
     * 批量插入项目年度计划到变更表
     *
     * @param proId
     * @param pcId
     */
    private void insertTaskPlan(Integer proId, Integer pcId) throws Exception {
        List<Map<String, Object>> list = handlerService.findBySql("select * from gq_scheduleplantask where delflag = '0' and proid = " + proId);

        if (CollectionUtils.isNotEmpty(list)) {
            Map<String, List<String>> convertMap = new HashMap<>();
            convertMap.computeIfAbsent("id", key -> new ArrayList<>()).add("taskid");

            List<String> expFields = new ArrayList<>();
            expFields.add("isreadonly");

            List<Map<String, Object>> insertList = new ArrayList<>();
            for (Map<String, Object> map : list) {
                Map<String, Object> addMap = tableService.convertMap("gq_scheduleplantask", "gq_pctaskchg", map, convertMap, expFields);
                addMap.put("pcid", pcId);// 项目变更id
                addMap.put("status", map.get("status"));// 状态
                insertList.add(addMap);
            }

            if (CollectionUtils.isNotEmpty(insertList)) {
                handlerService.batchInsert("prochangeApp", "gq_pctaskchg", insertList);

                // 转换前置和父级集合
                taskService.updParentIdAndPredecessors("prochangeApp", "gq_pctaskchg", "proid = " + proId + " and pcid = " + pcId);
            }

            List<Map<String, Object>> tcTaskList = handlerService.findBySql("select * from gq_pctaskchg where proid = " + proId + " and pcid = " + pcId);
            list = handlerService.findBySql("select * from gq_taskdeliverables where proid = " + proId);

            if (CollectionUtils.isNotEmpty(list)) {
                convertMap = new HashMap<>();
                convertMap.computeIfAbsent("id", key -> new ArrayList<>()).add("olddeliid");

                insertList = new ArrayList<>();
                for (Map<String, Object> map : list) {
                    Map<String, Object> addMap = tableService.convertMap("gq_taskdeliverables", "gq_taskdelichg", map, convertMap, null);
                    addMap.put("pcid", pcId);// 项目变更id
                    addMap.put("status", map.get("status"));// 状态

                    Integer taskId = MapUtils.getInteger(addMap, "taskid");
                    for (Map<String, Object> tcTaskMap : tcTaskList) {
                        Integer oldTaskId = MapUtils.getInteger(tcTaskMap, "taskid");

                        if (taskId.equals(oldTaskId)) {
                            addMap.put("pctaskid", MapUtils.getInteger(tcTaskMap, "id"));// 任务变更任务id
                            break;
                        }
                    }

                    insertList.add(addMap);
                }

                if (CollectionUtils.isNotEmpty(insertList)) {
                    handlerService.batchInsert("prochangeApp", "gq_taskdelichg", insertList);
                }
            }

        }
    }

    /**
     * 处理项目基础信息变更信息
     *
     * @param map
     * @param proid
     */
    private void dealBaseInfo(Map<String, Object> map, Integer proid) throws Exception {
        Map<String, Object> updMap = tableService.convertMap("gq_prochange", "gq_proaccount", map);
        updMap.put("id", proid);
        handlerService.update("gq_proaccount", updMap);
    }

    /**
     * 处理预算变更信息
     *
     * @param proId
     * @param year
     * @param pcId
     */
    private void dealBudget(Integer proId, String year, Integer pcId) throws Exception {
        // 保存项目年度预算版本信息
        Integer ppId = 0;
        String subjectNo = "";
        List<Map<String, Object>> proBudgetList = handlerService.findBySql("select * from gq_probudget where proid = " + proId + " and year = '" + year + "'");
        if (CollectionUtils.isNotEmpty(proBudgetList)) {
            ppId = MapUtils.getInteger(proBudgetList.get(0), "ppid");
            subjectNo = MapUtils.getString(proBudgetList.get(0), "subjectno");

            String conditionStr = " proid = " + proId + " and year = '" + year + "'";
            versionService.saveData("gq_probudget", conditionStr, proBudgetList);
        }

        // 查询项目变更年度预算变更
        List<Map<String, Object>> list = handlerService.findBySql("select * from gq_pcbudget where budgetamt != newbudgetamt and delflag = '0' and pcid = " + pcId);

        if (CollectionUtils.isNotEmpty(list)) {
            for (Map<String, Object> map : list) {
                Integer pbiid = MapUtils.getInteger(map, "pbiid");
                BigDecimal budgetAmt = new BigDecimal(MapUtils.getString(map, "budgetamt"));
                BigDecimal newBudgetAmt = new BigDecimal(MapUtils.getString(map, "newbudgetamt"));

                // 更新项目年度预算明细
                if (!pbiid.equals(0)) {
                    Map<String, Object> pbMap = handlerService.findOneBySql("select * from gq_probudget where pbiid = " + pbiid + " and proid = " + proId + " and year = '" + year + "'");
                    Integer id = MapUtils.getInteger(pbMap, "id");
                    // 更新年度预算信息
                    handlerService.updateBySql("update gq_probudget set budgetamt = " + newBudgetAmt + ", usefulamt = budgetamt - occupyamt - actualamt where id = " + id);

                    Map<String, Object> updMap = tableService.convertMap("gq_pcbudget", "gq_probudget", map);
                    updMap.put("id", id);
                    handlerService.update("gq_probudget", updMap);

                    // 查询项目概算
                    Map<String, Object> pblMap = handlerService.findOneBySql("select id, applyamt, budgetamt, chgbudgetamt from gq_pblbestimate where proid = " + proId + " and pbiid = " + pbiid);
                    BigDecimal applyAmt = new BigDecimal(MapUtils.getString(pblMap, "applyamt"));
                    BigDecimal pBudgetAmt = new BigDecimal(MapUtils.getString(pblMap, "budgetamt"));
                    BigDecimal chgBudgetAmt = new BigDecimal(MapUtils.getString(pblMap, "chgbudgetamt"));

                    if (newBudgetAmt.compareTo(budgetAmt) > 0) {
                        applyAmt = applyAmt.add(newBudgetAmt.subtract(budgetAmt));
                        pblMap.put("applyamt", applyAmt);

                        if (applyAmt.compareTo(pBudgetAmt) > 0) {
                            pblMap.put("budgetamt", applyAmt);
                            pblMap.put("usefulamt", 0);

                            chgBudgetAmt = applyAmt.subtract(pBudgetAmt);
                            pblMap.put("chgbudgetamt", chgBudgetAmt);
                        } else {
                            pblMap.put("usefulamt", pBudgetAmt.subtract(applyAmt));
                        }
                    } else if (newBudgetAmt.compareTo(budgetAmt) < 0) {
                        applyAmt = applyAmt.subtract(budgetAmt.subtract(newBudgetAmt));
                        pblMap.put("applyamt", applyAmt);
                        pblMap.put("usefulamt", pBudgetAmt.subtract(applyAmt));
                    }

                    // 更新项目概算信息
                    handlerService.update("gq_pblbestimate", pblMap);
                } else {
                    Integer pbidId = MapUtils.getInteger(map, "pbidid");
                    if (pbidId.equals(0)) {
                        // 插入新的预算信息
                        Map<String, List<String>> convertMap = new HashMap<>();
                        convertMap.computeIfAbsent("newbudgetamt", key -> new ArrayList<>()).add("budgetamt");
                        convertMap.computeIfAbsent("newbudgetamt", key -> new ArrayList<>()).add("usefulamt");
                        convertMap.computeIfAbsent("newcostsource", key -> new ArrayList<>()).add("costsource");
                        convertMap.computeIfAbsent("newcalculateway", key -> new ArrayList<>()).add("calculateway");
                        convertMap.computeIfAbsent("newsubjectnum", key -> new ArrayList<>()).add("subjectnum");
                        convertMap.computeIfAbsent("newsubjectdesc", key -> new ArrayList<>()).add("subjectdesc");
                        convertMap.computeIfAbsent("newcrdr", key -> new ArrayList<>()).add("crdr");

                        Map<String, Object> addMap = tableService.convertMap("gq_pcbudget", "gq_probudget", map, convertMap, null);
                        addMap.put("proid", proId);
                        addMap.put("subjectno", subjectNo);
                        addMap.put("ppid", ppId);

                        handlerService.insert("gq_probudget", addMap);
                    }
                }
            }
        }
    }

    /**
     * 处理项目资源变更信息
     *
     * @param list
     */
    private void dealResource(Integer proId, List<Map<String, Object>> list) throws Exception {
        for (Map<String, Object> map : list) {
            Integer id = MapUtils.getInteger(map, "prdid");

            if (!MapCustomUtils.compareMapValue(map.get("prid"), map.get("newprid"))
                    || !MapCustomUtils.compareMapValue(map.get("deptcode"), map.get("newdeptcode"))
                    || !MapCustomUtils.compareMapValue(map.get("prcategoryid"), map.get("newprcategoryid"))
                    || !MapCustomUtils.compareMapValue(map.get("duty"), map.get("newduty"))
                    || !MapCustomUtils.compareMapValue(map.get("status"), map.get("newstatus"))) {
                Map<String, Object> updMap = tableService.convertMap("gq_prdetailchg", "gq_proresource", map);
                updMap.put("id", id);
                updMap.put("proid", proId);
                handlerService.update("gq_proresource", updMap);
            }
        }
    }

    /**
     * 处理项目资源变更信息
     *
     * @param list
     */
    private void dealNewResource(List<Map<String, Object>> list) throws Exception {
        List<Map<String, Object>> insertList = new ArrayList<>();
        for (Map<String, Object> map : list) {
            Map<String, Object> addMap = tableService.convertMap("gq_prdetailchgnew", "gq_proresource", map, null, null);
            addMap.put("status", map.get("status"));
            insertList.add(addMap);
        }

        if (CollectionUtils.isNotEmpty(insertList)) {
            handlerService.batchInsert("proplanApp", "gq_proresource", insertList);
        }
    }

    /**
     * 处理项目交付物变更信息
     *
     * @param list
     */
    private void dealNewOutputPlan(List<Map<String, Object>> list) throws Exception {
        List<Map<String, Object>> insertList = new ArrayList<>();
        for (Map<String, Object> map : list) {
            Map<String, Object> addMap = tableService.convertMap("gq_popdtlchgnew", "gq_pbloutputplan", map, null, null);
            addMap.put("status", map.get("status"));
            insertList.add(addMap);
        }

        if (CollectionUtils.isNotEmpty(insertList)) {
            handlerService.batchInsert("proaccountApp", "gq_pbloutputplan", insertList);
        }
    }

    /**
     * 处理项目交付物变更信息
     *
     * @param list
     */
    private void dealOutputPlan(Integer proId, List<Map<String, Object>> list) throws Exception {
        List<Map<String, Object>> popList = handlerService.findBySql("select id from gq_pbloutputplan where proid = " + proId);

        for (Map<String, Object> popMap : popList) {
            Integer popId = MapUtils.getInteger(popMap, "id");
            boolean isExist = false;
            for (Map<String, Object> map : list) {
                Integer id = MapUtils.getInteger(map, "popdid");

                if (id.equals(popId)) {
                    isExist = true;
                    break;
                }
            }

            if (!isExist) {
                handlerService.updateBySql("delete from gq_pbloutputplan where id = " + popId);
            }
        }

        for (Map<String, Object> map : list) {
            Integer id = MapUtils.getInteger(map, "popdid");

            if (!MapCustomUtils.compareMapValue(map.get("delcategoryid"), map.get("newdelcategoryid"))
                    || !MapCustomUtils.compareMapValue(map.get("deltypeid"), map.get("newdeltypeid"))
                    || !MapCustomUtils.compareMapValue(map.get("delname"), map.get("newdelname"))
                    || !MapCustomUtils.compareMapValue(map.get("starttime"), map.get("newstarttime"))
                    || !MapCustomUtils.compareMapValue(map.get("endtime"), map.get("newendtime"))) {
                Map<String, Object> updMap = tableService.convertMap("gq_popdtlchg", "gq_pbloutputplan", map);
                updMap.put("proid", proId);
                updMap.put("id", id);
                handlerService.update("gq_pbloutputplan", updMap);
            }
        }
    }

    /**
     * 处理项目计划变更信息
     *
     * @param proId
     * @param pcId
     */
    private void dealTask(Integer proId, Integer pcId) throws Exception {
        // 查询并保存计划版本信息
        List<Map<String, Object>> proTaskList = handlerService.findBySql("select * from gq_scheduleplantask where proid = " + proId + " order by recordId");
        // 查询是否保存了任务计划数据
        List<Map<String, Object>> taskChgList = handlerService.findBySql("select * from gq_pctaskchg where pcid = " + pcId + " order by recordId");

        if (CollectionUtils.isNotEmpty(taskChgList)) {
            // 赋值项目信息
            Integer personInCharge = MapUtils.getInteger(taskChgList.get(0), "personincharge");
            Integer proLeader = MapUtils.getInteger(taskChgList.get(0), "proleader");
            String subjectNo = MapUtils.getString(taskChgList.get(0), "subjectno");

            Map<Integer, Integer> relateMap = new HashMap<>();

            Map<String, Object> setValues = new HashMap<>();
            setValues.put("personincharge", personInCharge);
            setValues.put("proleader", proLeader);
            setValues.put("subjectno", subjectNo);
            setValues.put("isissued", 1);
            setValues.put("status", "未开始");
            setValues.put("taskstatus", "未开始");

            List<String> filterFields = new ArrayList<>();
            filterFields.add("taskid");
            filterFields.add("tcid");

            // 插入新增任务到我的任务
            taskService.insertChgInfo(relateMap, "gq_scheduleplantask", "taskid", taskChgList, setValues,
                    filterFields, false, null, false, null, true, "parentId");

            Map<String, String> relateConvertMap = new HashMap<>();
            relateConvertMap.put("id", "taskid");

            List<String> expFields = new ArrayList<>();
            expFields.add("id");
            expFields.add("createtime");
            expFields.add("createuser");
            expFields.add("createuserdesc");
            expFields.add("updatetime");
            expFields.add("updateuser");
            expFields.add("status");
            expFields.add("taskstatus");
            expFields.add("version");
            expFields.add("recordId");
            expFields.add("uniqueId");
            expFields.add("hasChild");
            expFields.add("isissued");

            // 更新任务信息到我的任务或删除我的任务
            taskService.updateDeleteChgInfo(relateMap, relateConvertMap, taskChgList, proTaskList,
                    filterFields, "gq_scheduleplantask", true, "taskid", expFields, true, "parentId");

            // 更新任务信息
            taskService.updateTaskInfo("gq_scheduleplantask", "proid = " + proId, "level");

            // 下发任务
            handlerService.updateBySql("update gq_scheduleplantask set isissued = 1 where isissued = 0 and proid = " + proId);

            // 复制计划到我的任务
            taskService.copyToMyTask(proId);

            // 保存WBS计划版本
            if (!relateMap.isEmpty() && CollectionUtils.isNotEmpty(proTaskList)) {
                String conditionStr = " proid = " + proId;
                versionService.saveData("gq_scheduleplantask", conditionStr, proTaskList);
            }

            // 交付物处理
            setValues = new HashMap<>();
            setValues.put("status", "未交付");

            expFields = new ArrayList<>();
            expFields.add("pcid");
            expFields.add("pctaskid");

            taskService.dealDeliverables("quotetaskApp", "pcid = " + pcId, "olddeliid", "gq_taskdelichgnew",
                    "gq_taskdelichgdtl", "gq_taskdelichgdel", "gq_taskdeliverables", setValues, expFields, null);
        }
    }
}
